package com.tansun.easycare.core.config;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;

@Configuration
@EnableAspectJAutoProxy
@AutoConfigureAfter(DataSourceTransactionManagerAutoConfiguration.class)
@ConditionalOnProperty(prefix="txadvice",name = "requiredMethod")
public class TxAutoConfig {

	  private final TxAdviceProperties  adviceProperties;

      private final  PlatformTransactionManager  transactionManager;
      
      public  TxAutoConfig(TxAdviceProperties  adviceProperties,PlatformTransactionManager  transactionManager) {
	      this.adviceProperties = adviceProperties;
	      this.transactionManager = transactionManager;
	  }
	  
	  @Bean
	  @Primary
	  public  TransactionInterceptor  txAspactdvice() {
		  NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
		  RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
		  readOnlyTx.setReadOnly(true);
		  readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
		  RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED,
          Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
          requiredTx.setTimeout(5);
          Map<String, TransactionAttribute> txMap = new HashMap<>();
          String   required =adviceProperties.getRequiredMethod();
          String[] reqArg =StringUtils.split(required, ",");
          for (String  reqStr:reqArg) {
        	  txMap.put(reqStr, requiredTx);
          }
          String  readStr =adviceProperties.getReadOnlyMethod();
          String[] readArg = StringUtils.split(readStr, ",");
          for (String rs:readArg) {
        	  txMap.put(rs, readOnlyTx);
          }
          source.setNameMap( txMap );
          return new TransactionInterceptor(this.transactionManager ,source) ;	
	  }
	  
	  @Bean
	  public DefaultPointcutAdvisor defaultPointcutAdvisor(TransactionInterceptor transactionInterceptor){
	    	DefaultPointcutAdvisor pointcutAdvisor = new DefaultPointcutAdvisor();
	        pointcutAdvisor.setAdvice(transactionInterceptor);
	        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
	        pointcut.setExpression(adviceProperties.getExpression());
	        pointcutAdvisor.setPointcut(pointcut);
	        return pointcutAdvisor;
	  } 
}
